home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / Ddrawsup.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  7.2 KB  |  336 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19.  
  20. #define _WIN32_DCOM
  21.  
  22. #include <crtdbg.h>
  23.  
  24. #include <windows.h>
  25. #include <objbase.h>
  26.  
  27. #define DIRECTDRAW_VERSION 0x0300
  28.  
  29. #include <ddraw.h>
  30.  
  31. #include "ddrawsup.h"
  32. #include "vbitmap.h"
  33.  
  34. static BOOL com_initialized = FALSE;
  35. static IDirectDraw2 *lpdd = NULL;
  36. static DDCAPS g_devCaps;
  37. static DDSURFACEDESC ddsdPrimary;
  38. static IDirectDrawSurface *lpddsPrimary = NULL;
  39.  
  40. HRESULT InitCOM() {
  41.     HMODULE hModOLE = LoadLibrary("ole32.dll");
  42.     HRESULT hr;
  43.     
  44.     if (hModOLE) {
  45.         FARPROC fp = GetProcAddress(hModOLE, "CoInitializeEx");
  46.  
  47.         if (fp) {
  48.             hr = ((HRESULT (__stdcall *)(void *, DWORD))fp)(NULL, COINIT_MULTITHREADED);
  49.             FreeLibrary(hModOLE);
  50.  
  51.             return hr;
  52.         }
  53.  
  54.         FreeLibrary(hModOLE);
  55.     }
  56.  
  57.     return CoInitialize(NULL);
  58. }
  59.  
  60. bool DDrawDetect() {
  61.     HRESULT res;
  62.  
  63.     // first, try to initialize COM...
  64.  
  65.     _RPT0(0,"DirectDraw support: Initializing COM\n");
  66.  
  67.     if (FAILED(CoInitialize(NULL)))
  68. //    if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
  69. //        return false;
  70.  
  71.     // good, now let's get a IDirectDraw2 object
  72.  
  73.     _RPT0(0,"DirectDraw support: Getting IDirectDraw2 interface\n");
  74.  
  75.     res = CoCreateInstance(CLSID_DirectDraw, NULL, CLSCTX_ALL, IID_IDirectDraw2, (LPVOID *)&lpdd);
  76.     if (!FAILED(res))
  77.         res = lpdd->Initialize(NULL);
  78.  
  79.     if (FAILED(res)) {
  80.         CoUninitialize();
  81.         return false;    // damn!
  82.     }
  83.  
  84.     // looks like we have directdraw support....
  85.  
  86.     lpdd->Release();
  87.     lpdd = NULL;
  88.  
  89.     CoUninitialize();
  90.  
  91.     return true;
  92. }
  93.  
  94. BOOL DDrawInitialize(HWND hwnd) {
  95.     HRESULT res;
  96.  
  97.     // first, try to initialize COM...
  98.  
  99.     _RPT0(0,"DirectDraw support: Initializing COM\n");
  100.  
  101.     if (FAILED(CoInitialize(NULL)))
  102.         return FALSE;
  103.  
  104.     com_initialized = TRUE;
  105.  
  106.     // good, now let's get a IDirectDraw2 object
  107.  
  108.     _RPT0(0,"DirectDraw support: Getting IDirectDraw2 interface\n");
  109.  
  110.     res = CoCreateInstance(CLSID_DirectDraw, NULL, CLSCTX_ALL, IID_IDirectDraw2, (LPVOID *)&lpdd);
  111.     if (!FAILED(res))
  112.         res = lpdd->Initialize(NULL);
  113.  
  114.     if (FAILED(res)) return FALSE;    // damn!
  115.  
  116.     // retrieve dev caps
  117.  
  118.     // why the hell can't I get caps on my laptop!?
  119.  
  120. #if 0
  121.     g_devCaps.dwSize = sizeof(DDCAPS);
  122.  
  123.     res = lpdd->GetCaps(&g_devCaps, NULL);
  124.     if (FAILED(res))
  125.         return FALSE;
  126. #endif
  127.     // set cooperative level
  128.  
  129.     if (DD_OK != lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL))
  130.         return FALSE;
  131.  
  132.     // create primary surface
  133.  
  134.     _RPT0(0,"Creating primary surface\n");
  135.  
  136.     memset(&ddsdPrimary, 0, sizeof(ddsdPrimary));
  137.     ddsdPrimary.dwSize = sizeof(ddsdPrimary);
  138.     ddsdPrimary.dwFlags = DDSD_CAPS;
  139.     ddsdPrimary.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  140.     res = lpdd->CreateSurface(&ddsdPrimary, &lpddsPrimary, NULL );
  141.  
  142.     if (res != DD_OK)
  143.         return FALSE;
  144.  
  145.     return TRUE;
  146. }
  147.  
  148.  
  149. void DDrawDeinitialize() {
  150.     // Deallocate primary surface
  151.  
  152.     if (lpddsPrimary) {
  153.         lpddsPrimary->Release();
  154.         lpddsPrimary = NULL;
  155.     }
  156.  
  157.     // Deallocate the IDirectDraw2 object
  158.  
  159.     if (lpdd) {
  160.         lpdd->Release();
  161.  
  162.         lpdd = NULL;
  163.     }
  164.  
  165.     // Deinitialize COM
  166.  
  167.     if (com_initialized) {
  168.         CoUninitialize();
  169.  
  170.         com_initialized = FALSE;
  171.     }
  172.  
  173. }
  174.  
  175. IDirectDraw2 *DDrawObtainInterface() {
  176.     return lpdd;
  177. }
  178.  
  179. IDirectDrawSurface *DDrawObtainPrimary() {
  180.     return lpddsPrimary;
  181. }
  182.  
  183. ///////////////////////////////////////////////////////////////////////////
  184.  
  185. class DDrawSurface : public IDDrawSurface {
  186. private:
  187.     IDirectDrawSurface *lpdds;
  188.  
  189.     bool fIsLocked;
  190.  
  191. public:
  192.  
  193.     DDrawSurface(IDirectDrawSurface *lpdds);
  194.     ~DDrawSurface();
  195.     bool Lock(VBitmap *pvbm);
  196.     bool LockInverted(VBitmap *pvbm);
  197.     void Unlock();
  198.     void SetColorKey(COLORREF rgb);
  199.     void MoveOverlay(long x, long y);
  200.     void SetOverlayPos(RECT *pr);
  201.  
  202.     IDirectDrawSurface *getSurface();
  203.  
  204. };
  205.  
  206. IDDrawSurface *CreateDDrawSurface(IDirectDrawSurface *lpdds) {
  207.     return new DDrawSurface(lpdds);
  208. }
  209.  
  210. DDrawSurface::DDrawSurface(IDirectDrawSurface *lpdds) {
  211.     this->lpdds = lpdds;
  212.     fIsLocked = false;
  213. }
  214.  
  215. DDrawSurface::~DDrawSurface() {
  216.     Unlock();
  217.     lpdds->Release();
  218. }
  219.  
  220. bool DDrawSurface::Lock(VBitmap *pvbm) {
  221.     HRESULT res;
  222.     DDSURFACEDESC ddsd;
  223.  
  224.     if (fIsLocked)
  225.         return false;
  226.  
  227.     // *sigh*...
  228.  
  229.     memset(&ddsd, 0, sizeof ddsd);
  230.     ddsd.dwSize = sizeof ddsd;
  231.  
  232.     while(DD_OK != (res = lpdds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR|DDLOCK_WRITEONLY/*|DDLOCK_NOSYSLOCK*/, NULL))) {
  233. //    while(DD_OK != (res = lpdds->Lock(NULL, &ddsd, DDLOCK_WRITEONLY | DDLOCK_NOSYSLOCK, NULL))) {
  234.  
  235.         if (res == DDERR_SURFACELOST) {
  236.             res = lpdds->Restore();
  237.  
  238.             if (res != DD_OK)
  239.                 return false;
  240.         } else if (res == DDERR_WASSTILLDRAWING)
  241.             continue;
  242.  
  243.         // WinNT is lame -- doesn't like NOSYSLOCK.
  244.  
  245.         res = lpdds->Lock(NULL, &ddsd, DDLOCK_WRITEONLY, NULL );
  246.  
  247.         if (res == DD_OK)
  248.             break;
  249.  
  250.         if (res == DDERR_SURFACELOST) {
  251.  
  252.             // dammit!!!!
  253.  
  254.             res = lpdds->Restore();
  255.  
  256.             if (res != DD_OK)
  257.                 return false;
  258.  
  259.         } else if (res != DDERR_WASSTILLDRAWING) {
  260.             return false;
  261.         }
  262.     }
  263.  
  264.     // surface locked... translate DDSURFACEDESC struct to VBitmap
  265.  
  266.     pvbm->data        = (Pixel *)ddsd.lpSurface;
  267.     pvbm->palette    = NULL;
  268.     pvbm->w            = ddsd.dwWidth;
  269.     pvbm->h            = ddsd.dwHeight;
  270.     pvbm->pitch        = ddsd.lPitch;
  271.     pvbm->depth        = ddsd.ddpfPixelFormat.dwRGBBitCount;
  272.     pvbm->modulo    = ddsd.lPitch - (ddsd.dwWidth*ddsd.ddpfPixelFormat.dwRGBBitCount)/8;
  273.     pvbm->size        = pvbm->pitch * pvbm->h;
  274.     pvbm->offset    = 0;
  275.  
  276.     fIsLocked = true;
  277.  
  278.     return true;
  279. }
  280.  
  281. bool DDrawSurface::LockInverted(VBitmap *pvbm) {
  282.     if (!Lock(pvbm))
  283.         return false;
  284.  
  285.     pvbm->modulo    = pvbm->modulo-2*pvbm->pitch;
  286.     pvbm->pitch        = -pvbm->pitch;
  287.     pvbm->data        = (Pixel *)((char *)pvbm->data + pvbm->size + pvbm->pitch);
  288.  
  289.     return true;
  290. }
  291.  
  292. void DDrawSurface::Unlock() {
  293.  
  294.     if (!fIsLocked)
  295.         return;
  296.  
  297.     // not like we care if an unlock fails...
  298.  
  299.     lpdds->Unlock(NULL);
  300.  
  301.     fIsLocked = false;
  302. }
  303.  
  304. void DDrawSurface::SetColorKey(COLORREF rgb) {
  305.     DDCOLORKEY ddck;
  306.  
  307.     ddck.dwColorSpaceLowValue = rgb;
  308.     ddck.dwColorSpaceHighValue = rgb;
  309.  
  310.     lpdds->SetColorKey(DDCKEY_DESTOVERLAY, &ddck);
  311. }
  312.  
  313. void DDrawSurface::MoveOverlay(long x, long y) {
  314.     lpdds->SetOverlayPosition(x, y);
  315. }
  316.  
  317. void DDrawSurface::SetOverlayPos(RECT *pr) {
  318.     RECT r2 = *pr;
  319.     HRESULT res;
  320.  
  321. //    --r2.right;
  322. //    --r2.bottom;
  323.  
  324.     res = lpdds->UpdateOverlay(NULL, lpddsPrimary, &r2, DDOVER_SHOW, NULL);
  325.     if (res == DDERR_SURFACELOST) {
  326.         res = lpdds->Restore();
  327.  
  328.         if (!FAILED(res))
  329.             res = lpdds->UpdateOverlay(NULL, lpddsPrimary, &r2, DDOVER_SHOW, NULL);
  330.     }
  331. }
  332.  
  333. IDirectDrawSurface *DDrawSurface::getSurface() {
  334.     return lpdds;
  335. }
  336.